//
//  UserAccount.swift
//  Weibo
//
//  Created by 张文文 on 15/6/1.
//  Copyright (c) 2015年 zww. All rights reserved.
//

import UIKit
import Alamofire

///

/**
在 Swift 中，如果要实现 description，需要遵守一个协议 Printable

归档&解档
1. 遵守 NSCoding 协议
2. 实现两个方法

所有的专门用来设计的构造器，必须给所有非空属性设置数值
*/
class UserAccount: NSObject, Printable, NSCoding {
    //用于调用access_token，接口获取授权后的access token。
    let access_token: String
    //access_token的生命周期，单位是秒数
    let expires_in: NSTimeInterval
    //过期日期
    /// 如果是开发者，有效期是5年
    /// 如果是普通用户，有效期是26小时
    let expireDate: NSDate
    //当前授权用户的UID
    let uid: String
    
    
    init(dict: [String: AnyObject]) {
        access_token = dict["access_token"] as! String
        expires_in = dict["expires_in"] as! NSTimeInterval
        expireDate = NSDate(timeIntervalSinceNow: expires_in)
        uid = dict["uid"] as! String
        
    }
    
    // 在 swift 中，如果类函数要访问某一个属性值，需要使用到 static
    // 归档路径 － Document，可以 iTunes 备份的，由应用程序产生的重要数据
    // 目前为止，在 swift 中，不允许定义 class 的"存储型"常量，需要使用 static
    static let accountPath = (NSSearchPathForDirectoriesInDomains(NSSearchPathDirectory.DocumentDirectory, NSSearchPathDomainMask.UserDomainMask, true).last as! String).stringByAppendingPathComponent("account.plist")
    
    ///去新浪服务器加载 AccessToken
    class func loadAccessToken(params:[String: String], completion:(account: UserAccount?, error: NSError?)->()) {
        
        let urlString = "https://api.weibo.com/oauth2/access_token"
        
        Alamofire.request(.POST, urlString, parameters: params).responseJSON() { (_, _, JSON, error) in
            

             // 如果出现错误，直接回调并且返回
            if JSON == nil || error != nil {
                completion(account: nil, error: error)
                return
            }
            
            // JSON 有可能是字典也有可能是数组
            // 字典转模型
            let account = UserAccount(dict: JSON as! [String : AnyObject])
            
         
            
             // 键值归档保存数据
            NSKeyedArchiver.archiveRootObject(account, toFile: UserAccount.accountPath)
            //回调
            completion(account: account, error: nil)
           
        }.responseString() { (_, _, JSONString, _)  in
            println(JSONString)
        }
    
    }
    
    /**
    从本地沙盒读取用户数据(解档)
    
    *** 在什么地方调用 - AppDelegate 中调用
    */
    class func loadUserAccount() -> UserAccount? {
        if let account = NSKeyedUnarchiver.unarchiveObjectWithFile(UserAccount.accountPath) as? UserAccount {
            
            // 考虑到一个细节 - 过期日期，一旦过期，需要用户重新登录
            // 过期日期比当前日期大，所以比较结果是`降序`
            if account.expireDate.compare(NSDate()) == NSComparisonResult.OrderedDescending {
                return account
            }
        }
        
        return nil
    }
    
    override var description:String {
        let properties = ["access_token", "expires_in", "uid", "expireDate"]
        return "\(dictionaryWithValuesForKeys(properties))"
    
    }
    // MARK: - 归档 & 解档方法
    ///归档器 编码器
    func encodeWithCoder(aCoder: NSCoder){
        aCoder.encodeObject(access_token, forKey: "access_token")
        aCoder.encodeDouble(expires_in, forKey: "expires_in")
        aCoder.encodeObject(expireDate, forKey: "expireDate")
        aCoder.encodeObject(uid, forKey: "uid")
        
    }
    // 提示：解档的方法，一定要加一个 required 关键字
    // 目的是表示一点遵守了 NSCoding 协议，init 的构造方法是必须实现的
    // 解码器的方法
    required init(coder aDecoder: NSCoder){
        access_token = aDecoder.decodeObjectForKey("access_token") as! String
        // 如果编码的是基本数据类型，能够保证一定解码到结果，可以省略 !
        // 可以按照 Xcode 的智能提示操作
        expires_in = aDecoder.decodeDoubleForKey("expires_in") as NSTimeInterval
        expireDate = aDecoder.decodeObjectForKey("expireDate") as! NSDate
        uid = aDecoder.decodeObjectForKey("uid") as! String
        
    }
   
}
